/*
 * Copyright (C) 2020 FoilPlanet
 *
 */

#include "anbox/codec/audio_sink.h"
#include "anbox/logger.h"

#include <stdexcept>

#include <boost/throw_exception.hpp>

namespace {
const constexpr size_t max_queue_size{16};
}

using namespace anbox::codec;

AudioSink::AudioSink(const std::shared_ptr<anbox::Runtime> &runtime) 
  : queue_(max_queue_size)
{
  // TODO
}

AudioSink::~AudioSink()
{
  // NOTHING
}

bool AudioSink::connect_audio()
{
  // TODO
  return true;
}

void AudioSink::disconnect_audio()
{
  // TODO
}

void AudioSink::read_data(std::uint8_t *buffer, int size)
{
  std::unique_lock<std::mutex> l(lock_);
  const auto wanted = size;
  int count = 0;
  auto dst = buffer;

  while (count < wanted) {
    if (read_buffer_left_ > 0) {
      size_t avail = std::min<size_t>(wanted - count, read_buffer_left_);
      memcpy(dst + count,
             read_buffer_.data() + (read_buffer_.size() - read_buffer_left_),
             avail);
      count += avail;
      read_buffer_left_ -= avail;
      continue;
    }

    bool blocking = (count == 0);
    auto result = -EIO;
    if (blocking)
      result = queue_.pop_locked(&read_buffer_, l);
    else
      result = queue_.try_pop_locked(&read_buffer_);

    if (result == 0) {
      read_buffer_left_ = read_buffer_.size();
      continue;
    }

    if (count > 0) break;

    return;
  }
}

void AudioSink::write_data(const std::vector<std::uint8_t> &data) {
  if (!is_connect()) {
    // WARNING("Audio server not connected, skipping %d bytes", data.size());
  } else {
    std::unique_lock<std::mutex> l(lock_);
    graphics::Buffer buffer{data.data(), data.data() + data.size()};
    queue_.push_locked(std::move(buffer), l);
  }
}